<template>
	<div class="default-main">

		<!-- 当前角色信息 -->
		<el-descriptions v-if="isAssigningPermission" id="authority-descriptions" ref="elDescriptionsRef" :column="1" border direction="horizontal"
		                 style="width: 50%;margin-bottom: 20px" title="当前角色">
			<template #extra>
				<el-button v-auth="'sys-authority:saveRoleAuthority'" :loading="saveRoleAuthorityLoading || tableLoading" icon="el-icon-CircleCheck" type="primary"
				           @click="saveRoleAuthority">保存
				</el-button>
				<el-button :loading="tableLoading" icon="el-icon-Back" type="primary" @click="backToRolePage">返回</el-button>
			</template>
			<el-descriptions-item align="center" label-align="left" label-class-name="description-label" min-width="100">
				<template #label>
					<icon name="fa fa-user"></icon>
					角色编码
				</template>
				{{ role.roleCode }}
			</el-descriptions-item>
			<el-descriptions-item align="center" label-align="left" label-class-name="description-label" min-width="100">
				<template #label>
					<icon name="fa fa-user-circle"></icon>
					角色名称
				</template>
				{{ role.roleName }}
			</el-descriptions-item>
			<el-descriptions-item align="center" label-align="left" label-class-name="description-label" min-width="100">
				<template #label>
					<icon name="fa fa-file-text-o"></icon>
					描述
				</template>
				{{ role.description }}
			</el-descriptions-item>
		</el-descriptions>

		<!-- 按钮区 -->
		<div id="authority-buttons" style="display: flex;width: 50%">
			<el-button v-if="!isAssigningPermission" :loading="tableLoading" icon="el-icon-Refresh"
			           type="primary" @click="handleSearch">{{ $t('tagsView.refresh') }}
			</el-button>
			<el-button v-if="isAssigningPermission" :loading="tableLoading" icon="el-icon-Refresh"
			           type="primary"
			           @click="handleCheckBox(undefined).then(() => {messageSuccess(`已重置角色【${authorityStore.editingRole!.roleName}（${authorityStore.editingRole!.roleCode}）】的权限`)})">
				{{ '重置' }}
			</el-button>
			<el-button :icon="expandAll ? 'el-icon-CaretBottom' : 'el-icon-CaretRight'" type="primary"
			           @click="handleExpand">{{ expandAllTitle }}
			</el-button>
			<el-button v-if="!isAssigningPermission" v-auth="'sys-authority:saveAuthority'" icon="el-icon-Plus" type="primary" @click="toAdd(undefined)">{{
					'新增根节点'
				}}
			</el-button>
			<div v-if="isAssigningPermission" style="margin-left: auto">
				<el-text>快速选择：</el-text>
				<el-select v-auth="'sys-authority:saveAuthority'" clearable filterable style="width: 220px" value-key="id" @change="selectedRoleChanged">
					<el-option v-for="role in displayedRoleList" :key="role.id" :label="`${role.roleName}（${role.roleCode}）`" :value="role"/>
				</el-select>
			</div>
		</div>

		<!-- 权限树 -->
		<cus-table-title id="authority-table-table" icon="local-cus-authority" label="权限"/>
		<auth-table ref="treeTableRef" v-model:expandAll="expandAll" :columns="columns" :data="authorityTree" :default-expand-all="defaultExpandAll"
		            :draggable="false" :loading="tableLoading" :max-height="tableMaxHeight" :selection="isAssigningPermission"
		            @tree-table-selection-change="selectionChange">
			<template v-slot:title="{scope}">
				<span v-if="scope!.row.type === 1">{{ $t(scope!.row.title) }}</span>
				<span v-else>{{ scope!.row.name }}</span>
			</template>
			<template v-slot:icon="{scope}">
				<icon v-if="scope?.row.icon" :name="scope!.row.icon"></icon>
			</template>
			<template v-slot:type="{scope}">
				<span>{{ formatMenuType(scope!.row) }}</span>
			</template>
			<template v-slot:operation="{scope}">
				<div>
					<el-button v-if="scope!.row.type === 1 || scope!.row.type === 4" v-auth="'sys-authority:saveAuthority'"
					           icon="el-icon-Plus" size="small" type="primary" @click="toAdd(scope!.row)">
						{{ $t('system.authority.addChildren') }}
					</el-button>
					<el-button v-auth="'sys-authority:saveAuthority'" icon="el-icon-Edit" size="small" type="primary"
					           @click="toUpdate(scope!.row)">
						{{ $t('table.edit') }}
					</el-button>
					<el-popconfirm
							:hide-after="0"
							:title="'删除该'+(scope!.row.type===1?'菜单':scope!.row.type===2?'页面组件':scope!.row.type===3?'接口':'结构')+'（'+scope!.row.name+'）和所有下级权限，是否继续？'"
							confirm-button-type="danger" width="auto" @confirm="deleteAuthority(scope!.row)">
						<template #reference>
							<el-button v-auth="'sys-authority:deleteAuthority'" icon="el-icon-Delete" size="small" type="danger">删除
							</el-button>
						</template>
					</el-popconfirm>
				</div>
			</template>
		</auth-table>

		<!-- 对话框（新增、修改） -->
		<el-dialog v-model="dialogVisible" :close-on-click-modal="false" :title="dialogTitle" append-to-body center class="cus-dialog" destroy-on-close draggable
		           width="50%">
			<el-form ref="editFormRef" :model="form" :rules="rules" label-position="right" label-width="auto" style="padding-right: 30px">
				<el-form-item label="父级菜单" prop="parentName">
					<div style="display: flex;justify-content: space-between;align-items: center;width: 100%">
						<el-tag type="info">{{ form.parentName || '无' }}</el-tag>
						<el-button v-if="dialogTitle === '更新权限信息'" plain size="small" type="primary" @click="toSelectParentMenu">变更</el-button>
					</div>
				</el-form-item>
				<el-form-item label="类型" prop="type">
					<business-code-select v-model="form.type" :disabled-value-array="['5']" code-type="authorityType"/>
				</el-form-item>
				<el-row :gutter="20" justify="space-between">
					<el-col :span="12">
						<el-form-item label="名称" prop="name">
							<el-input v-model="form.name" :placeholder="getNamePlaceholder(form.type)"/>
						</el-form-item>
					</el-col>
					<el-col :span="12">
						<el-form-item label="同级排序" prop="sort">
							<el-input-number v-model="form.sort" :max="MAX_INTEGER" :min="1" :step="1" class="w100" controls-position="right" step-strictly/>
						</el-form-item>
					</el-col>
				</el-row>
				<!-- 菜单 -->
				<div v-if="form.type === 1">
					<el-row :gutter="20" justify="space-between">
						<el-col :span="12">
							<el-form-item label="地址" prop="path">
								<el-input v-model="form.path" clearable placeholder="无论是否为顶级菜单，均以 / 开头"/>
							</el-form-item>
						</el-col>
						<el-col :span="12">
							<el-form-item label="文件位置" prop="component">
								<el-input v-model="form.component" clearable placeholder=".vue文件的路径，如：views/system/user.vue">
									<template #prepend>/src/</template>
								</el-input>
							</el-form-item>
						</el-col>
					</el-row>
					<el-row :gutter="20" justify="space-between">
						<el-col :span="12">
							<el-form-item label="重定向地址" prop="redirect">
								<el-input v-model="form.redirect" clearable placeholder="路由重定向（redirect字段），请填写路由的path"/>
							</el-form-item>
						</el-col>
						<el-col :span="12">
							<el-form-item label="标题" prop="title">
								<el-input v-model="form.title" clearable placeholder="国际化的 key，如：route.systemManagement"/>
							</el-form-item>
						</el-col>
					</el-row>
					<el-row :gutter="20" justify="space-between">
						<el-col :span="12">
							<el-form-item label="图标" prop="icon">
								<el-input v-model="form.icon" clearable/>
							</el-form-item>
						</el-col>
						<el-col :span="12">
							<el-form-item label="页面缓存" prop="keepAlive">
								<el-switch v-model="form.keepAlive" :active-value="1" :inactive-value="0"/>
							</el-form-item>
						</el-col>
					</el-row>
					<el-row :gutter="20" justify="space-between">
						<el-col :span="12">
							<el-form-item label="隐藏菜单" prop="hidden">
								<el-switch v-model="form.hidden" :active-value="1" :inactive-value="0"/>
							</el-form-item>
						</el-col>
						<el-col :span="12">
							<el-form-item label="固定标签" prop="affix">
								<el-switch v-model="form.affix" :active-value="1" :inactive-value="0"/>
							</el-form-item>
						</el-col>
					</el-row>
				</div>
				<!-- 页面组件 -->
				<div v-if="form.type === 2">
					<el-form-item label="资源编码" prop="resources">
						<el-input v-model="form.resources" clearable/>
					</el-form-item>
				</div>
				<!-- 接口 -->
				<div v-if="form.type === 3">
					<el-form-item label="url" prop="url">
						<el-input v-model="form.url" clearable placeholder="以 / 开头，按ant-style匹配"/>
					</el-form-item>
				</div>
				<!-- 仅结构 -->
				<div v-if="form.type === 4"></div>
			</el-form>
			<template #footer>
				<el-button v-auth="'sys-authority:saveAuthority'" :loading="saveAuthorityLoading" icon="el-icon-CircleCheck"
				           type="primary" @click="saveAuthority">
					{{ $t('table.save') }}
				</el-button>
				<el-button icon="el-icon-CircleClose" type="warning" @click="dialogVisible = false">
					{{ $t('table.cancel') }}
				</el-button>
			</template>
		</el-dialog>

		<!-- 对话框（变更父节点） -->
		<el-dialog v-model="changeParentMenuVisible" :close-on-click-modal="false" append-to-body center class="cus-dialog" destroy-on-close draggable
		           title="变更父节点" width="25%">
			<el-tree
					ref="treeRef"
					:data="menuTreeOptions"
					:props="treeOptionProps"
					:render-after-expand="false"
					check-strictly
					node-key="id"
					show-checkbox
					@check="parentMenuChecked"
			/>
			<template #footer>
				<el-button icon="el-icon-CircleCheck" type="primary" @click="confirmParentMenu">
					{{ $t('table.save') }}
				</el-button>
				<el-button icon="el-icon-CircleClose" type="warning" @click="changeParentMenuVisible = false">
					{{ $t('table.cancel') }}
				</el-button>
			</template>
		</el-dialog>

	</div>
</template>

<script lang="ts" name="AuthorityManagement" setup>

import {validateCh} from '@/utils/validateUtil'
import {
	deleteAuthorityApi,
	getAllAuthorityIdByRoleIdApi,
	getAllRoleApi,
	getAuthorityInfoApi,
	saveAuthorityApi,
	saveRoleAuthorityApi
} from '@/api/system/authority.api'
import type {RuleItemValidator} from '@/model/global-import'
import {computed, nextTick, onActivated, onMounted, reactive, ref, watch} from 'vue'
import {useI18n} from 'vue-i18n'
import {cloneDeep, debounce, type DebouncedFunc, map, pick} from 'lodash-es'
import {closeLoading, findInTreeArray, focusFormErrorElement, messageError, messageSuccess, showLoading, treeArrayIterator, treeIterator} from '@/utils/commonUtil'
import type {DescriptionInstance, FormInstance, FormRules} from 'element-plus'
import {ElTree} from 'element-plus'
import {useAuthorityStore} from '@/stores/modules/authority.store'
import {onBeforeRouteLeave, useRoute} from 'vue-router'
import Icon from '@/components/icon.vue'
import CusTableTitle from '@/components/cus-table-title.vue'
import AuthTable from '@/components/auth-table.vue'
import {removeRouteByName, routePush, updateDynamicRoutes} from '@/utils/routeUtil'
import {useEventListener} from '@vueuse/core'
import {useWebConfigStore} from '@/stores/modules/webConfig.store'
import {calcMaxHeight} from '@/utils/layoutUtil'
import type {TreeOptionProps} from 'element-plus/es/components/tree/src/tree.type'
import BusinessCodeSelect from '@/components/business-code-select.vue'
import {MAX_INTEGER} from '@/utils/constantsUtil'
import router from '@/router'
import {homeRoute} from '@/router/static'
import {useUserStore} from '@/stores/modules/user.store'
import {useNavTabsStore} from '@/stores/modules/navTabs.store'

const {t} = useI18n(),
		route = useRoute(),
		userStore = useUserStore(),
		authorityStore = useAuthorityStore(),
		navTabsStore = useNavTabsStore(),
		webConfigStore = useWebConfigStore(),
		elDescriptionsRef = ref<DescriptionInstance>(),
		treeTableRef = ref(),
		editFormRef = ref<FormInstance>(),
		treeRef = ref<InstanceType<typeof ElTree>>(),
		role = reactive({
			roleCode: undefined,
			roleName: undefined,
			description: undefined
		}),
		isAssigningPermission = ref(false),
		tableLoading = ref(false),
		saveRoleAuthorityLoading = ref(false),
		saveAuthorityLoading = ref(false),
		expandAll = ref(false),
		defaultExpandAll = ref(false),
		tableMaxHeight = ref<number>(),
		expandAllTitle = computed(() => {
			return expandAll.value ? t('system.authority.foldAllTitle') : t('system.authority.expandAllTitle')
		}),
		dialogVisible = ref(false),
		dialogTitle = ref<string>(),
		authorityTree = ref<AuthorityVo[]>([]),
		authorityList = ref<SysAuthority[]>([]),
		selectedAuthorityList = ref<AuthorityRow[]>([]),
		roleList = ref<SysRole[]>([]),
		displayedRoleList = ref<SysRole[]>([]),
		selectedRoleChanged = (val?: SysRole) => {
			if (val) {
				handleCheckBox(val.id).then(() => {
					messageSuccess(`已选中角色【${val.roleName}（${val.roleCode}）】的权限，别忘了保存哦~`)
				})
			}
		},
		iconClassFunction = (data: AuthorityRow): string | undefined => {
			switch (data.type) {
				case 1:
					return 'fa fa-edge'
				case 2:
					return 'fa fa-hand-pointer-o'
				case 3:
					return 'fa fa-exchange'
				case 4:
					return 'fa fa-folder-open-o'
				case 5:
					return 'fa fa-external-link'
				default:
					return undefined
			}
		},
		columns = ref<ColumnsOption[]>([
			{
				label: '内容',
				key: 'title',
				expandable: true,
				iconClassFunction: iconClassFunction,
				align: 'left',
				headerAlign: 'center',
				minWidth: 300,
				showOverflowTooltip: true
			},
			{label: t('system.authority.iconView'), key: 'icon', width: 150, showOverflowTooltip: false},
			{label: t('system.authority.name'), key: 'name', minWidth: 180, showOverflowTooltip: true},
			{label: t('system.authority.type'), key: 'type', minWidth: 100, showOverflowTooltip: true},
			{label: '路由', key: 'path', minWidth: 150, showOverflowTooltip: true},
			{label: t('system.authority.component'), key: 'component', minWidth: 200, showOverflowTooltip: true},
			{label: 'url', key: 'url', minWidth: 200, showOverflowTooltip: true},
			{label: t('system.authority.resources'), key: 'resources', minWidth: 200, showOverflowTooltip: true},
			{label: t('system.authority.sort'), key: 'sort', minWidth: 80, showOverflowTooltip: true},
			{label: t('table.actions'), key: 'operation', minWidth: 270, fixed: 'right', showOverflowTooltip: false}
		]),
		form = reactive<SysAuthority & { parentName?: string }>({
			// 公共属性
			id: undefined,
			parentId: undefined,
			type: undefined,
			name: undefined,
			sort: undefined,
			// 菜单所需属性
			title: undefined,
			path: undefined,
			component: undefined,
			redirect: undefined,
			hidden: 0,
			icon: undefined,
			keepAlive: 1,
			affix: 0,
			// 按钮所需属性
			resources: undefined,
			// 接口所需属性
			url: undefined,
			// 前端附加属性
			parentName: undefined
		}),
		_validateCh: RuleItemValidator = (rule, value, callback) => {
			if (value && validateCh(value)) {
				callback(Error())
			}
			callback()
		},
		rules = reactive<FormRules>({
			// 公共属性
			type: [
				{required: true, message: t('system.authority.ruleMessage.type'), trigger: 'change'}
			],
			name: [
				{required: true, message: t('system.authority.ruleMessage.name'), trigger: 'change'},
				{min: 1, max: 100, message: t('system.authority.ruleMessage.name_length'), trigger: 'change'}
			],
			sort: [
				{required: true, message: t('system.authority.ruleMessage.sort'), trigger: 'change'}
			],
			// 菜单所需属性
			title: [
				{required: true, message: t('system.authority.ruleMessage.title'), trigger: 'change'},
				{min: 1, max: 100, message: t('system.authority.ruleMessage.title_length'), trigger: 'change'}
			],
			path: [
				{required: true, message: t('system.authority.ruleMessage.path'), trigger: 'change'},
				{min: 1, max: 100, message: t('system.authority.ruleMessage.path_length'), trigger: 'change'}
			],
			component: [
				{required: false, message: t('system.authority.ruleMessage.component'), trigger: 'change'},
				{min: 1, max: 100, message: t('system.authority.ruleMessage.component_length'), trigger: 'change'}
			],
			hidden: [
				{required: true, message: '请选择是否隐藏', trigger: 'change'}
			],
			icon: [
				{required: false, max: 100, message: t('system.authority.ruleMessage.icon'), trigger: 'change'}
			],
			keepAlive: [
				{required: true, message: '请选择是否缓存', trigger: 'change'}
			],
			affix: [
				{required: true, message: '请选择是否固定标签', trigger: 'change'}
			],
			// 按钮所需属性
			resources: [
				{required: true, message: t('system.authority.ruleMessage.resources'), trigger: 'change'},
				{min: 1, max: 255, message: t('system.authority.ruleMessage.resources_length'), trigger: 'change'},
				{validator: _validateCh, trigger: 'change', message: '不能包含中文'}
			],
			// 接口所需属性
			url: [
				{required: true, message: '请输入接口的url', trigger: 'change'}
			]
		}),
		// 计算表格最大高度
		getTableMaxHeight: DebouncedFunc<() => typeof getTableMaxHeight> = debounce(() => {
			tableMaxHeight.value = calcMaxHeight('#authority-descriptions', '#authority-buttons', '#authority-table-table')
			return getTableMaxHeight
		}, 100, {
			leading: true,
			trailing: false,
			maxWait: 100
		}),
		// 初始化快速选择角色下拉框
		treeOptionProps = reactive<TreeOptionProps>({
			label: 'label',
			children: 'children',
			disabled: 'disabled'
		}),
		menuTreeOptions = ref<MenuTreeOption[]>([]), changeParentMenuVisible = ref(false), getNamePlaceholder = (type: SysAuthority['type']) => {
			switch (type) {
				case 1:
					return '路由名称（name字段），请填写英文'
				case 2:
					return '页面组件名称，支持中文'
				case 3:
					return '接口名称，支持中文'
				case 4:
					return '结构名称，支持中文'
				case 5:
					return '外部链接名称，支持中文'
			}
		},
		toSelectParentMenu = () => {
			menuTreeOptions.value = cloneDeep(authorityTree.value)
			treeArrayIterator(menuTreeOptions.value, (item: MenuTreeOption) => {
				item.label = item.type === 1 ? t(item.title!) : item.name
				// 只能选择【菜单】和【仅结构】类型的菜单为上级
				item.disabled = item.type !== 1 && item.type !== 4
			})
			// 不能选择自身和自身的子级
			const self: MenuTreeOption | undefined = findInTreeArray(menuTreeOptions.value, treeNode => treeNode.id === form.id!)
			if (!self) {
				messageError('无法匹配菜单')
				return
			}
			treeIterator(self, authorityVo => authorityVo.disabled = true)
			// 添加一个【无】选项
			menuTreeOptions.value.unshift({
				id: 0,
				label: '无',
				disabled: false,
				children: []
			})
			changeParentMenuVisible.value = true
			// 设置当前选中的父级菜单，并展开父级节点
			nextTick(() => {
				treeRef.value?.setCheckedKeys([form.parentId!])
				treeRef.value?.setCurrentKey(form.parentId!, true)
			})
		},
		parentMenuChecked = (data: MenuTreeOption, info: TreeCheckedInfo) => {
			if (info.checkedKeys.length > 1) {
				treeRef.value?.setCheckedKeys([data.id!])
			}
		},
		confirmParentMenu = () => {
			const checkedNodes: MenuTreeOption[] | undefined = treeRef.value?.getCheckedNodes()
			if (!checkedNodes || checkedNodes.length === 0) {
				messageError('请选择父级菜单')
				return
			}
			if (checkedNodes.length > 1) {
				messageError('只能选择一个父级菜单')
				return
			}
			const parent: MenuTreeOption = checkedNodes[0]
			if (parent.id === 0) {
				form.parentName = '无'
				form.parentId = 0
			} else {
				form.parentName = parent.type === 1 ? t(parent.title!) : parent.name
				form.parentId = parent.id
			}
			changeParentMenuVisible.value = false
		},
		handleSearch = () => {
			if (tableLoading.value) {
				return
			}
			tableLoading.value = true
			getAuthorityInfoApi().then(response => {
				defaultExpandAll.value = expandAll.value
				authorityList.value = response.data.authorityList
				authorityTree.value = response.data.authorityTree
				if (!isAssigningPermission.value) {
					tableLoading.value = false
				}
			}).catch(() => {
				tableLoading.value = false
			})
		},
		checkIfAssigningPermission = () => {
			if (authorityStore.editingRole) {
				isAssigningPermission.value = true
				Object.assign(role, pick(authorityStore.editingRole, Object.keys(role)))
				if (columns.value[columns.value.length - 1].key === 'operation') {
					columns.value.pop()
				}
			} else {
				isAssigningPermission.value = false
				if (columns.value[columns.value.length - 1].key !== 'operation') {
					columns.value.push({label: t('table.actions'), key: 'operation', minWidth: 270, fixed: 'right'})
				}
			}
		},
		handleCheckBox = async (roleId: number = authorityStore.editingRole!.id!) => {
			tableLoading.value = true
			try {
				selectedAuthorityList.value = []
				const authIdList = (await getAllAuthorityIdByRoleIdApi(roleId)).data
				treeTableRef.value.setSelection(authIdList)
			} finally {
				tableLoading.value = false
			}
		},
		selectionChange = (val: AuthorityRow[]) => {
			selectedAuthorityList.value = val
		},
		formatMenuType = (row: AuthorityRow) => {
			switch (row.type) {
				case 1:
					return '菜单'
				case 2:
					return '页面组件'
				case 3:
					return '接口'
				case 4:
					return '仅结构'
				case 5:
					return '外部链接'
				default:
					return ''
			}
		},
		resetForm = () => {
			form.id = undefined
			form.parentId = undefined
			form.type = undefined
			form.name = undefined
			form.sort = undefined
			form.title = undefined
			form.path = undefined
			form.component = undefined
			form.redirect = undefined
			form.hidden = 0
			form.icon = undefined
			form.keepAlive = 1
			form.affix = 0
			form.resources = undefined
			form.url = undefined
			form.parentName = undefined
		},
		handleExpand = () => {
			expandAll.value = !expandAll.value
		},
		toAdd = (parent?: AuthorityRow) => {
			dialogTitle.value = '新增权限'
			resetForm()
			// 一级菜单
			if (!parent) {
				form.parentId = 0
				const sortArray = map(authorityTree.value, 'sort')
				form.sort = Math.max(...<number[]>sortArray, sortArray.length) + 1
			}
			// 子菜单
			else {
				form.parentId = parent.id
				const sortArray = map(parent.children, value => {
					return value.sort ?? 0
				})
				form.sort = Math.max(...sortArray, sortArray.length) + 1
				form.parentName = parent.type === 1 ? t(parent.title!) : parent.name
			}
			dialogVisible.value = true
			nextTick(() => {
				editFormRef.value?.clearValidate()
			})
		},
		toUpdate = (row: AuthorityRow) => {
			dialogTitle.value = '编辑权限信息'
			resetForm()
			Object.assign(form, pick(row, Object.keys(form)))
			const parentNode: SysAuthority | undefined = row.parentId === 0 ? undefined : authorityList.value.find(item => item.id === row.parentId)
			if (parentNode) {
				form.parentName = parentNode.type === 1 ? t(parentNode.title!) : parentNode.name
			}
			dialogVisible.value = true
			nextTick(() => {
				editFormRef.value?.clearValidate()
			})
		},
		deleteAuthority = (row: AuthorityRow) => {
			showLoading()
			deleteAuthorityApi(row.id!).then(response => {
				messageSuccess(t('successMessage.delete'))
				userStore.modifyToken(response.data?.token, response.data?.expire)
				const buttons = response.data?.buttons
				if (buttons) {
					userStore.buttons = buttons
				}
				const menus = response.data?.menus
				if (menus) {
					userStore.dynamicMenus = menus
					// 更新动态路由
					updateDynamicRoutes()
					// 初始化菜单
					userStore.generateMenu()
					// 关闭所有没有权限的标签页
					navTabsStore.retainTheseTabs(menuVo => router.getRoutes().some(item => item.path === menuVo.meta.fullPath))
					// 如果当前路由已不存在，则跳转到首页
					if (!router.getRoutes().some(item => item.path === route.path)) {
						routePush(homeRoute)
						return
					}
				}
				handleSearch()
			}).finally(() => {
				closeLoading()
			})
		},
		saveAuthority = () => {
			editFormRef.value?.validate(isValid => {
				if (isValid) {
					// 根据权限的类型将数据库不需要的字段置空
					if (form.type === 1) {
						form.resources = undefined
						form.url = undefined
					} else if (form.type === 2) {
						form.title = undefined
						form.path = undefined
						form.component = undefined
						form.redirect = undefined
						form.hidden = undefined
						form.icon = undefined
						form.affix = undefined
						form.url = undefined
						form.keepAlive = undefined
					} else if (form.type === 3) {
						form.title = undefined
						form.path = undefined
						form.component = undefined
						form.redirect = undefined
						form.hidden = undefined
						form.icon = undefined
						form.keepAlive = undefined
						form.affix = undefined
						form.resources = undefined
					} else if (form.type === 4) {
						form.title = undefined
						form.path = undefined
						form.component = undefined
						form.redirect = undefined
						form.hidden = undefined
						form.icon = undefined
						form.keepAlive = undefined
						form.affix = undefined
						form.resources = undefined
						form.url = undefined
					} else {
						messageError('权限类型无效')
						return
					}
					saveAuthorityLoading.value = true
					saveAuthorityApi(form).then(response => {
						if (form.id) {
							messageSuccess(t('successMessage.update'))
						} else {
							messageSuccess(t('successMessage.add'))
						}
						userStore.modifyToken(response.data?.token, response.data?.expire)
						const buttons = response.data?.buttons
						if (buttons) {
							userStore.buttons = buttons
						}
						const menus = response.data?.menus
						if (menus) {
							userStore.dynamicMenus = menus
							// 删除上级权限或权限类型变化的路由，重新构建
							if (removeRouteByName(form.name!)) {
								// 关闭已被删除的标签页
								navTabsStore.retainTheseTabs(menuVo => router.getRoutes().some(item => item.path === menuVo.meta.fullPath))
							}
							// 更新动态路由
							updateDynamicRoutes()
							// 初始化菜单
							userStore.generateMenu()
							// 关闭所有没有权限的标签页
							navTabsStore.retainTheseTabs(menuVo => router.getRoutes().some(item => item.path === menuVo.meta.fullPath))
							// 如果当前路由已不存在，则跳转到首页
							if (!router.getRoutes().some(item => item.path === route.path)) {
								routePush(homeRoute)
								return
							}
						}
						dialogVisible.value = false
						handleSearch()
					}).finally(() => {
						saveAuthorityLoading.value = false
					})
				} else {
					focusFormErrorElement()
				}
			})
		},
		saveRoleAuthority = () => {
			saveRoleAuthorityLoading.value = true
			const data: SaveRoleAuthorityRequest = {
				role: {
					id: authorityStore.editingRole!.id!,
					roleCode: authorityStore.editingRole!.roleCode!,
					roleName: authorityStore.editingRole!.roleName!
				},
				authorityList: []
			}
			for (const authority of selectedAuthorityList.value) {
				data.authorityList.push({
					id: authority.id!,
					name: authority.name!
				})
			}
			saveRoleAuthorityApi(data).then(response => {
				messageSuccess(t('successMessage.save'))
				userStore.modifyToken(response.data?.token, response.data?.expire)
				const buttons = response.data?.buttons
				if (buttons) {
					userStore.buttons = buttons
				}
				const menus = response.data?.menus
				if (menus) {
					userStore.dynamicMenus = menus
					// 更新动态路由
					updateDynamicRoutes()
					// 初始化菜单
					userStore.generateMenu()
					// 关闭所有没有权限的标签页
					navTabsStore.retainTheseTabs(menuVo => router.getRoutes().some(item => item.path === menuVo.meta.fullPath))
					// 如果当前路由已不存在，则跳转到首页
					if (!router.getRoutes().some(item => item.path === route.path)) {
						routePush(homeRoute)
						return
					}
				}
			}).finally(() => {
				saveRoleAuthorityLoading.value = false
			})
		},
		backToRolePage = () => {
			routePush({name: 'RoleManagement'})
		},
		initQuickSelect = () => {
			if (isAssigningPermission.value) {
				getAllRoleApi().then(response => {
					roleList.value = response.data
					displayedRoleList.value = roleList.value.filter(item => item.roleCode !== authorityStore.editingRole!.roleCode)
				})
			}
		}

watch(authorityList, () => {
	if (isAssigningPermission.value) {
		handleCheckBox()
	}
})

// 第一次打开该tab页或刷新页面后执行
onMounted(() => {
	nextTick(() => {
		useEventListener(window, 'resize', getTableMaxHeight()!)
	})
	checkIfAssigningPermission()
	handleSearch()
	initQuickSelect()
})

// 该页面开启缓存且首次或后续进入时执行，刷新页面不执行
onActivated(() => {
	nextTick(() => {
		useEventListener(window, 'resize', getTableMaxHeight()!)
	})
	checkIfAssigningPermission()
	handleSearch()
	initQuickSelect()
})

onBeforeRouteLeave(() => {
	authorityStore.editingRole = undefined
	window.removeEventListener('resize', getTableMaxHeight)
})

</script>

<style lang="scss" scoped>
:deep(.description-label) {
	width: 100px;
}
</style>
